﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using tiDE.API;
using WeifenLuo.WinFormsUI.Docking;
using System.IO;
using tiDE.Runtime;
using tiDE.API.Utility;
using tiDE.SourceInsight;

namespace tiDE
{
    public partial class SolutionExplorer : DockContent
    {
        public event EventHandler<FileActionEventArgs> OpenFileRequested;
        public event EventHandler<NewFileEventArgs> NewFileRequested;
        public event EventHandler<NewFileEventArgs> AddExistingRequested;
        public event EventHandler<FileActionEventArgs> DeleteFileRequested;
        public event EventHandler<RenameFileEventArgs> RenameFileRequested;
        public event EventHandler<NavigateToLocationEventArgs> NavigateToLocationRequested;

        public SolutionExplorer()
        {
            InitializeComponent();
            treeView1.BeforeExpand += new TreeViewCancelEventHandler(treeView1_BeforeExpand);
        }

        bool suppressExpand = false;
        TreeNode nodeToExpand = null;

        void treeView1_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            if (!doNotSuppress)
            {
                nodeToExpand = e.Node;
                e.Cancel = true;
            }
            doNotSuppress = false;
        }

        public void UpdateSolution(Solution solution)
        {
            treeView1.Nodes.Clear();
            if (solution == null)
            {
                treeView1.Nodes.Add(new TreeNode("No Solution."));
                return;
            }
            TreeNode baseNode = new TreeNode(solution.Name, 0, 0);
            baseNode.ContextMenuStrip = contextMenuStripProject;
            baseNode.Tag = solution;
            foreach (Project project in solution.Projects)
            {
                TreeNode projectNode = new TreeNode(project.Name);
                projectNode.ContextMenuStrip = contextMenuStripSolution;
                projectNode.Tag = project;
                if (!string.IsNullOrEmpty(project.IconFile))
                {
                    if (File.Exists("Templates\\" + project.IconFile))
                    {
                        imageList1.Images.Add(Image.FromFile("Templates\\" + project.IconFile));
                        projectNode.ImageIndex = imageList1.Images.Count - 1;
                        projectNode.SelectedImageIndex = projectNode.ImageIndex;
                    }
                    else if (File.Exists(RuntimeData.tiDEUserDirectory + "\\" + project.IconFile))
                    {
                        imageList1.Images.Add(Image.FromFile(RuntimeData.tiDEUserDirectory + "\\" + project.IconFile));
                        projectNode.ImageIndex = imageList1.Images.Count - 1;
                        projectNode.SelectedImageIndex = projectNode.ImageIndex;
                    }
                }
                foreach (string file in project.Files)
                {
                    if (file.Contains("\\") || file.Contains("/"))
                    {
                        // Needs folder
                    }
                    else
                    {
                        TreeNode fileNode = new TreeNode(file, 1, 1);
                        fileNode.Tag = project.RootDirectory + "\\" + file;
                        fileNode.ContextMenuStrip = contextMenuStripFile;
                        if (File.Exists(tiDEWindow.CurrentSolutionDirectory + project.RootDirectory + "\\" + file))
                        {
                            imageList1.Images.Add(Icon.ExtractAssociatedIcon(tiDEWindow.CurrentSolutionDirectory + project.RootDirectory + "\\" + file));
                            fileNode.ImageIndex = imageList1.Images.Count - 1;
                            // Generate source location insight
                            ISourceInsightProvider provider = InsightManager.GetProviderForExtension(file.Substring(file.LastIndexOf('.')));
                            if (provider != null)
                            {
                                StreamReader reader = new StreamReader(tiDEWindow.CurrentSolutionDirectory + "\\" + project.RootDirectory + "\\" + file);
                                string source = reader.ReadToEnd();
                                List<SourceLocation> locations = provider.GetSourceLocations(source, tiDEWindow.CurrentSolutionDirectory + "\\" + project.RootDirectory + "\\" + file);
                                foreach (SourceLocation location in locations)
                                {
                                    TreeNode locationNode = new TreeNode(location.Name);
                                    locationNode.ImageIndex = 4;
                                    locationNode.SelectedImageIndex = 4;
                                    locationNode.Tag = new SourceLocationDetail()
                                    {
                                        SourceLocation = location,
                                        SourceFile = project.RootDirectory + "\\" + file,
                                    };
                                    fileNode.Nodes.Add(locationNode);
                                }
                            }
                        }
                        else
                        {
                            fileNode.ImageIndex = 3;
                            fileNode.ForeColor = Color.Gray;
                        }
                        fileNode.SelectedImageIndex = fileNode.ImageIndex;
                        projectNode.Nodes.Add(fileNode);
                    }
                }
                baseNode.Nodes.Add(projectNode);
            }
            treeView1.Nodes.Add(baseNode);
        }

        private void treeView1_DoubleClick(object sender, EventArgs e)
        {
            suppressExpand = true;
            if (NavigateToLocationRequested != null && treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is SourceLocationDetail)
                {
                    SourceLocationDetail detail = (SourceLocationDetail)treeView1.SelectedNode.Tag;
                    NavigateToLocationRequested(this, new NavigateToLocationEventArgs(
                        detail.SourceFile, detail.SourceLocation.Line,
                        detail.SourceLocation.Index));
                    return;
                }
            }
            if (OpenFileRequested != null && treeView1.SelectedNode != null)
            {
                if (!(treeView1.SelectedNode.Tag is Project))
                {
                    if (!(treeView1.SelectedNode.Tag is Solution))
                        OpenFileRequested(this, new FileActionEventArgs(treeView1.SelectedNode.Tag.ToString()));
                }
            }
        }

        private void newToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is Project)
                {
                    if (NewFileRequested != null)
                        NewFileRequested(this, new NewFileEventArgs(treeView1.SelectedNode.Tag as Project));
                }
            }
        }

        private void treeView1_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
                treeView1.SelectedNode = treeView1.GetNodeAt(e.Location);
        }

        private void existingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is Project)
                {
                    if (AddExistingRequested != null)
                        AddExistingRequested(this, new NewFileEventArgs(treeView1.SelectedNode.Tag as Project));
                }
            }
        }

        private void renameToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is string)
                {
                    treeView1.SelectedNode.BeginEdit();
                }
            }
        }

        private void deleteToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is string)
                {
                    if (DeleteFileRequested != null)
                        DeleteFileRequested(this, new FileActionEventArgs((string)treeView1.SelectedNode.Tag));
                }
            }
        }

        private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is string)
                {
                    if (DataConverter.StripDirectory((string)treeView1.SelectedNode.Tag) == e.Label)
                        return;
                    if (RenameFileRequested != null)
                        RenameFileRequested(this, new RenameFileEventArgs((string)treeView1.SelectedNode.Tag, e.Label));
                }
            }
        }

        private void openFolderInWindowsExplorerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is Solution)
                {
                    System.Diagnostics.Process.Start("explorer.exe",
                        tiDEWindow.CurrentSolutionDirectory);
                }
            }
        }

        private void viewInWindowsExplorerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (treeView1.SelectedNode != null)
            {
                if (treeView1.SelectedNode.Tag is Project)
                {
                    System.Diagnostics.Process.Start("explorer.exe",
                        tiDEWindow.CurrentSolutionDirectory + (treeView1.SelectedNode.Tag as Project).RootDirectory);
                }
            }
        }

        bool doNotSuppress = false;

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (nodeToExpand != null)
            {
                if (!suppressExpand)
                {
                    doNotSuppress = true;
                    nodeToExpand.Expand();
                }
                suppressExpand = false;
                nodeToExpand = null;
            }
        }
    }

    public class FileActionEventArgs : EventArgs
    {
        public string File { get; set; }

        public FileActionEventArgs(string File)
        {
            this.File = File;
        }
    }

    public class NewFileEventArgs : EventArgs
    {
        public Project Project { get; set; }

        public NewFileEventArgs(Project Project)
        {
            this.Project = Project;
        }
    }

    public class RenameFileEventArgs : EventArgs
    {
        public string File { get; set; }
        public string NewName { get; set; }

        public RenameFileEventArgs(string File, string NewName)
        {
            this.File = File;
            this.NewName = NewName;
        }
    }

    public class NavigateToLocationEventArgs : EventArgs
    {
        public string File { get; set; }
        public int Line { get; set; }
        public int Index { get; set; }

        public NavigateToLocationEventArgs(string File, int Line, int Index)
        {
            this.File = File;
            this.Line = Line;
            this.Index = Index;
        }
    }

    internal struct SourceLocationDetail
    {
        public SourceLocation SourceLocation;
        public string SourceFile;
    }
}
